home *** CD-ROM | disk | FTP | other *** search
- name qfn
- title QFN.ASM --- qualify file name
- page 55,132
- ;
- ;
- ; QFN.ASM -- Qualify File Name
- ;
- ; Copyright (C) 1988 Ziff Davis
- ; by Ray Duncan Feb. 1988
- ;
- ; Call with: DS:SI = filename address
- ; AX = length
- ;
- ; Returns: Carry = clear if filename OK
- ; DS:SI = qualified filename
- ; AX = length
- ; or
- ; Carry = set if bad filename
- ;
- ; Registers other than DS:SI
- ; and AX are preserved.
- ;
-
- DGROUP group _DATA
-
- _DATA segment word public 'DATA'
-
- cdrive db 0 ; current drive
- cpath db '\',64 dup (0) ; current directory
-
- tbuff db 64 dup (0) ; target directory
-
- qbuff db 'X:\' ; qualified pathname
- db 64 dup (0)
-
- fname dw ? ; filename address
- flen dw ? ; filename length
-
- _DATA ends
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP
-
- public qfn ; make visible to Linker
-
- qfn proc near ; qualify file name
-
- push bx ; save registers
- push cx
- push dx
- push di
- push es
-
- mov flen,ax ; save length and
- mov fname,si ; address of filename
-
- mov ax,ds ; make DGROUP addressable
- mov es,ax ; with ES register
-
- ; save current drive...
- mov ah,19h ; fxn 19h = get drive
- int 21h ; transfer to MS-DOS
- mov cdrive,al ; save it
-
- ; save current directory...
- ; DS:SI = buffer
- mov si,offset DGROUP:cpath+1
- mov ah,47h ; fxn 47h = get directory
- mov dl,0 ; drive = current
- int 21h ; transfer to MS-DOS
-
- ; did caller specify drive?
- mov di,fname ; get address of name
- mov cx,flen ; get length of name
-
- cmp cx,2 ; if drive, length must
- ; be >= 2 chars.
- jl qfn2 ; too short, no drive
-
- ; check for drive delimiter
- cmp byte ptr [di+1],':'
- jne qfn2 ; no delimiter, jump
-
- mov dl,[di] ; get ASCII drive code
- or dl,20h ; fold to lower case
- sub dl,'a' ; convert it to binary
- mov ah,0eh ; fxn 0eh = select drive
- int 21h ; transfer to MS-DOS
-
- ; get current drive to
- ; make sure drive selected
- mov ah,19h ; fxn 19h = get current drive
- int 21h ; transfer to MS-DOS
- cmp dl,al ; current = requested?
- je qfn1 ; jump if select succeeded
- jmp qfn8 ; exit, select failed
-
- qfn1: add di,2 ; bump pointer past drive
- sub cx,2 ; and decrement length
-
- qfn2: ; save current directory
- ; again for new drive...
- ; DS:SI = buffer
- mov si,offset DGROUP:cpath+1
- mov ah,47h ; fxn 47h = get directory
- mov dl,0 ; drive = current
- int 21h ; transfer to MS-DOS
-
- ; scan off path if any
- push di ; save start of path
- mov al,'\' ; path delimiter
-
- qfn3: mov fname,di ; save path pointer
- mov flen,cx ; save path length
- jcxz qfn4 ; jump if none left
-
- repne scasb ; any '\' left in path?
- je qfn3 ; loop if '\' found
-
- qfn4: pop si ; recover starting address
- ; of path portion
-
- ; copy path to local buffer
- ; and make it ASCIIZ...
- mov di,offset DGROUP:tbuff
- mov cx,fname ; calculate path length
- sub cx,si
- jz qfn6 ; jump, no path at all
- cmp cx,1 ; root directory?
- je qfn5 ; jump if root
- dec cx ; else discard last '\'
-
- qfn5: rep movsb ; transfer path and
- xor al,al ; append null byte
- stosb
-
- ; now make target directory
- ; the current directory...
- mov dx,offset DGROUP:tbuff
- mov ah,3bh ; fxn 3BH = select directory
- int 21h ; transfer to MS-DOS
- jc qfn8 ; jump, no such directory
-
- qfn6: ; build up full pathname...
-
- mov ah,19h ; get current drive
- int 21h ; transfer to MS-DOS
- add al,'A' ; convert binary to ASCII
- mov qbuff,al ; store ASCII drive code
-
- ; get current directory
- mov dl,0 ; DL = 0 for default drive
- ; DS:SI = buffer address
- mov si,offset DGROUP:qbuff+3
- mov ah,47h ; fxn 47h = get current dir
- int 21h ; transfer to MS-DOS
- jc qfn8 ; jump if error
-
- ; point to path component
- mov di,offset DGROUP:qbuff+3
- cmp byte ptr [di],0 ; is current directory
- ; the root directory?
- je qfn7 ; yes, jump
-
- xor al,al ; scan for null byte at
- mov cx,-1 ; end of path name
- repne scasb ; and append backslash
- mov byte ptr [di-1],'\'
-
- qfn7: ; now append filename
- ; to drive and path...
- mov si,fname ; filename address
- cmp byte ptr [si],'.'
- je qfn8 ; exit if directory alias
- mov cx,flen ; filename length
- rep movsb ; copy it
-
- ; set DS:SI = address
- mov si,offset DGROUP:qbuff
- mov ax,di ; and AX = length of
- sub ax,si ; fully qualified filename
-
- call makelc ; fold filename to lower
- ; case to make it pretty
-
- clc ; Carry = false to
- ; indicate success
-
- jmp qfn9 ; jump to common exit
-
- qfn8: ; come here if any
- ; error detected...
-
- stc ; Carry = true to
- ; indicate error
-
- qfn9: pushf ; save Carry flag
- push ax ; save final length
-
- ; restore original directory
- mov dx,offset DGROUP:cpath
- mov ah,3bh ; fxn 3BH = select directory
- int 21h ; transfer to MS-DOS
-
- mov dl,cdrive ; restore original drive
- mov ah,0eh ; fxn 0EH = set drive
- int 21h ; transfer to MS-DOS
-
- pop ax ; restore length
- popf ; and Carry flag
-
- pop es ; restore other affected
- pop di ; registers
- pop dx
- pop cx
- pop bx
-
- ret ; back to caller
-
- qfn endp
-
-
- makelc proc near ; string -> lower case
- ; DS:SI = address
- ; AX = length
-
- push bx ; save BX contents
- xor bx,bx ; BX will be pointer
-
- mlc1: ; change A-Z to a-z
- cmp byte ptr [bx+si],'A'
- jb mlc2
- cmp byte ptr [bx+si],'Z'
- ja mlc2
- or byte ptr [bx+si],20h
-
- mlc2: inc bx ; advance through string
- cmp bx,ax ; done with string yet?
- jne mlc1 ; no, check next char.
-
- pop bx ; restore BX and
- ret ; return to caller
-
- makelc endp
-
- _TEXT ends
-
- end
-